package cn.tramy.pinxian.wind.handler.registry

import cn.tramy.pinxian.common.util.logger
import cn.tramy.pinxian.wind.handler.HandlerInfo
import cn.tramy.pinxian.wind.handler.processor.AnnotationHandlerProcessor
import cn.tramy.pinxian.wind.handler.processor.DefaultAnnotationHandlerProcessor
import java.util.concurrent.ConcurrentHashMap

class DefaultHandlerRegistry : HandlerRegistry {

    companion object {
       private val LOGGER= logger(DefaultHandlerRegistry::class.java)
    }

    private var annotationHandlerProcessor: AnnotationHandlerProcessor = DefaultAnnotationHandlerProcessor()


    private val groupHandlerInfoMap = mutableMapOf<String, MutableMap<Class<*>, MutableSet<HandlerInfo<Any>>>>()


    constructor()

    constructor(annotationHandlerProcessor: AnnotationHandlerProcessor) {
        this.annotationHandlerProcessor = annotationHandlerProcessor
    }

    override fun <T : Annotation> registerHandler(handlerObj: Any, annotationClazz: Class<T>, group: String) {

        val handlerInfos = annotationHandlerProcessor.process(handlerObj, annotationClazz)


        val handlerInfoMap = this.groupHandlerInfoMap.getOrPut(group, { ConcurrentHashMap() })

        handlerInfos.forEach {
            handlerInfoMap.getOrPut(it.messageType, { mutableSetOf() }).add(it)
            LOGGER.debug("register handler [$it] for event [${it.messageType}] with group [$group]")
        }
    }

    override fun <T : Any> findHandlers(parameterType: Class<T>, group: String): List<HandlerInfo<Any>> {

        val result = mutableListOf<HandlerInfo<Any>>()

        this.groupHandlerInfoMap[group]?.let {
            it.filterKeys { it.isAssignableFrom(parameterType) }
                    .values.forEach { result.addAll(it.toList()) }
        }


        return result
    }

    override fun <T : Any> handlerCount(parameterType: Class<T>, group: String): Int = this.findHandlers(parameterType).size
}